﻿using System.Collections.Concurrent;

namespace BlazorAdmin.Tcp.Server
{
    /// <summary>
    /// TCP连接池
    /// </summary>
    public sealed class TcpConnPool<T> where T : TcpToken
    {
        private readonly ConcurrentDictionary<string, T> connPool;

        public TcpConnPool(int maxCapacity)
        {
            connPool = new ConcurrentDictionary<string, T>(1, maxCapacity);
        }

        /// <summary>
        /// 当连接池加入新的TCP连接时，将引发此事件
        /// </summary>
        public event EventHandler<T>? OnConnAdd;

        /// <summary>
        /// 当连接池连移除某个TCP连接时，将引发此事件
        /// </summary>
        public event EventHandler<T>? OnConnRemove;

        /// <summary>
        /// 获取连接的会话
        /// </summary>
        /// <param name="predicate">匹配方法</param>
        /// <returns></returns>
        internal IEnumerable<T> GetConnections(Func<T, bool>? predicate = null)
        {
            var query = connPool.Values.AsEnumerable();
            if (null == predicate)
                return query;

            return from t in query where predicate(t) select t;
        }

        /// <summary>
        /// 添加TCP连接
        /// </summary>
        /// <param name="token">连接会话对象</param>
        internal void Add(T token)
        {
            if (!connPool.ContainsKey(token.Key) && connPool.TryAdd(token.Key, token))
                OnConnAdd?.Invoke(this, token);
        }

        /// <summary>
        /// 移除TCP连接
        /// </summary>
        /// <returns></returns>
        internal bool Remove(string key)
        {
            if (connPool.TryRemove(key, out T? token))
            {
                OnConnRemove?.Invoke(this, token);
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断TCP连接否存在
        /// </summary>
        /// <param name="key">TCP会话ID</param>
        /// <returns></returns>
        internal bool IsExistConectionn(string key) => connPool.ContainsKey(key);
    }
}
